﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.IO;
using System.Drawing;
using System.Globalization;
using System.ComponentModel;
using System.Data;
using System.Windows.Forms;


namespace ProyectoPractico
{
    class FuzzyArtmap
    {
        private const int CANTEJ = 1;//Variable 
        private const int SALIDAS = 5;
        //ATRIBUTOS*****************************************************************************************
        private Art A;
        private Art B;
        private CargadorImagen cargadorImagenes;
        private int cantidadEntradas;
        private ArrayList vectorEntradas;
        private ArrayList vectorSalidas;
        private MapField mapfield;
        private int cantClasificados;
        //METODOS*****************************************************************************************
        
        /*
        * Constructor de la clase
        */
        public FuzzyArtmap(int nEntrada/*, string nombreArchImagenes, int nSalida, double[,] entrada*/)
        {            
            vectorEntradas = new ArrayList();
            vectorSalidas = new ArrayList();
            cantidadEntradas = nEntrada;
            A = new Art(nEntrada*nEntrada,0.99/*,nSalida,entrada*/);
            B = new Art(SALIDAS,0.99);
            mapfield = new MapField();
        }

        public void cargarArchivoImagen(){
            try{
                string nombreArchImagenes = preguntarNombreArchivo("Indique el archivo que contiene la lista de imágenes");
                cargadorImagenes = new CargadorImagen(nombreArchImagenes);
            }catch(Exception e){
                MessageBox.Show("Se produjo un error cargando el archivo", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        //-------------------------------------------------------------------------------------------------
        /*
         * 
         */
        public void cargarEntradas()
        {
            int contador = 0;
            for (int x = 0; x < (cantidadEntradas ); x++)
            {
                for (int y = 0; y < (cantidadEntradas ); y++)
                {
                    vectorEntradas.Insert(contador, cargadorImagenes.getPixelFoto(x, y));
                    contador++;
                }
            }
        }

        private void vaciarVectores() {
            vectorEntradas.Clear();
            vectorSalidas.Clear();
            A.vaciarVectores();
            B.vaciarVectores();
        }
        //-------------------------------------------------------------------------------------------------

        /*
         * 
         */
        public void cargarSalidas() {
            string salida = cargadorImagenes.getIdentificador();
            for(int a=0; a<SALIDAS ; a++){
                int letra = int.Parse(((double)salida[a]).ToString()) - 64;// para dejar el numero de la letra del 1 al 26
                vectorSalidas.Insert(a, (1.0/27.0)*letra);
            }
        }



        //-------------------------------------------------------------------------------------------------

        /*
         * 
         */
        public void cargarPesos(int arch)
        {
            try
            {
                switch (arch)
                {
                    case 1://pesos ART A ida
                        A.cargarPesosIda(preguntarNombreArchivo("Ingrese el nombre del archivo con los pesos de ida del Art A"));
                        break;
                    case 2://pesos ART B ida
                        B.cargarPesosIda(preguntarNombreArchivo("Ingrese el nombre del archivo con los pesos de ida del Art B"));
                        break;
                    case 3://pesos ART B ida
                        mapfield.cargarMapField(preguntarNombreArchivo("Ingrese el nombre del archivo del MapField"));
                        break;
                }
            }catch(Exception e){
                MessageBox.Show("Se produjo un error con el archivo", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        //-------------------------------------------------------------------------------------------------

        /*
         * 
         */
        public void guardarPesos(int arch)
        {
            try
            {
                switch (arch)
                {
                    case 1://pesos ART A ida
                        A.guardarPesosIda(preguntarNombreArchivoGuardar("Ingrese el nombre del archivo donde guardar\n los pesos de ida del Art A"));
                        break;
                    case 2://pesos ART B ida
                        B.guardarPesosIda(preguntarNombreArchivoGuardar("Ingrese el nombre del archivo donde guardar\n los pesos de ida del Art B"));
                        break;
                    case 3://pesos ART B ida
                        mapfield.guardarEnArch(preguntarNombreArchivoGuardar("Ingrese el nombre del archivo donde guardar\n los valores del MapField"));
                        break;

                }
            }catch(Exception e){
                MessageBox.Show("Se produjo un error con el archivo", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }


        //-------------------------------------------------------------------------------------------------

        /*
         * Método que guarda los pesos de ida en un archivo
         */
        private string preguntarNombreArchivo(string pregunta)
        {
            bool seguir = false;
            string respuesta = " ";
            do
            {
                try
                {
                    MessageBox.Show(pregunta, "Fuzzy ArtMap", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    OpenFileDialog openFileDialog = new OpenFileDialog();
                    openFileDialog.Filter = "text files (*.txt)|*.txt";
                    openFileDialog.ShowDialog();
                    respuesta = openFileDialog.FileName;
                }
                catch (Exception e)
                {
                    MessageBox.Show("Se produjo un error con el archivo, intente nuevamente!", "Pesos", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    seguir = true;
                }

            } while (seguir);
            return respuesta;
        }

        private string preguntarNombreArchivoGuardar(string pregunta)
        {
            bool seguir = false;
            string respuesta = " ";
            do
            {
                try
                {
                    MessageBox.Show(pregunta, "Fuzzy ArtMap", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    SaveFileDialog saveFileDialog = new SaveFileDialog();
                    saveFileDialog.Filter = "text files (*.txt)|*.txt";
                    saveFileDialog.ShowDialog();
                    respuesta = saveFileDialog.FileName;
                }
                catch (Exception e)
                {
                    MessageBox.Show("Se produjo un error con el archivo, intente nuevamente!", "Pesos", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    seguir = true;
                }

            } while (seguir);
            return respuesta;
        }
        //-------------------------------------------------------------------------------------------------

        /*
         * Método que desencadena el entrenamiento de la red
         */
        public void entrenar(ref ProgressBar progreso,ref Label etq)
        {
            progreso.Value = 0;
            etq.Text = "0%";
            int cantImagenes = cargadorImagenes.getCantidadImagenes();

            for (int a = 0; a < cantImagenes;a++ )
            {

                //progreso.Increment((100 / cantImagenes));
                cargadorImagenes.cargarSiguiente();
                vaciarVectores();
                cargarEntradas();
                cargarSalidas();
                //bool seguir = false;
                int jB = clasificarEntradaB();//B.clasificarEntrada(vectorSalidas);
                
                clasificarEntradaA(jB);
                progreso.Value += (100 / cantImagenes);
                etq.Text = progreso.Value + "%";
                etq.Refresh();
                /*do
                {
                    
                    int jA = clasificarEntradaA(jB);// A.clasificarEntrada(vectorEntradas);
                    bool aceptado = mapfield.mapear(cargadorImagenes.getIdentificador(),jA, jB );
                    if (!aceptado)
                    {
                        seguir = true;
                        A.ajustarPesos(jA);
                    }
                } while (seguir);*/
            }
            cargadorImagenes.cerrarArchivoImagen();
        }


        private void clasificarEntradaA(int clasificadoB){
            A.calcularTs(vectorEntradas);
            bool mapeado = false;
            int clasificadoA=-1;
            while(!mapeado){
                clasificadoA = A.buscarPosibleApto();
                if(clasificadoA!=-1){
                    mapeado = this.mapfield.mapear(cargadorImagenes.getIdentificador(),clasificadoA,clasificadoB);
                    if(!mapeado){
                        A.aumentarParamV(clasificadoA);
                        A.descalificarNeurona(clasificadoA);
                    }
                }else{
                    clasificadoA = A.crearNuevaSalida();
                    mapeado = this.mapfield.mapear(cargadorImagenes.getIdentificador(), clasificadoA, clasificadoB);
                    if (!mapeado)
                    {
                        Console.WriteLine("No se cuenta con suficiente espacio");
                    }
                }
            }            
            A.ajustarPesos(clasificadoA);
            A.resetParamV();
            //Console.WriteLine( "Cant clasificados " + ++this.cantClasificados);
            //Console.WriteLine("Neurona " + clasificadoA + " con " + mapfield.getResultado(clasificadoA) + " ==" + clasificadoB);
        }

        private int clasificarEntradaB() {
            B.calcularTs(vectorSalidas);
            int clasificadoB = B.buscarPosibleApto();
            if (clasificadoB == -1) {
                clasificadoB = B.crearNuevaSalida();
            }
            if (clasificadoB > mapfield.getCantCategorias()-1) {
                B.ajustarPesos(clasificadoB);            
            }
            return clasificadoB;       
        }


        public string probar()
        {
            string respuesta = "";
            try
            {
                cargadorImagenes = new CargadorImagen();
                vaciarVectores();
                MessageBox.Show("A continuación ingrese la imagen que desea probar", "Fuzzy ArtMap", MessageBoxButtons.OK, MessageBoxIcon.Information);
                OpenFileDialog openFileDialog = new OpenFileDialog();
                openFileDialog.Filter = "text files (*.jpg)|*.jpg";
                openFileDialog.ShowDialog();
                string nombre = openFileDialog.FileName;
                cargadorImagenes.cargarImagenPrueba(nombre);
                cargarEntradas();
                //deberiamos de cargar los pesos
                //int jA = A.clasificarEntrada(vectorEntradas);
                A.calcularTs(vectorEntradas);
                int jA = A.buscarPosibleApto();
                respuesta = mapfield.getResultado(jA);
            }catch(Exception e){
                MessageBox.Show("Se produjo un error con el archivo", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            return respuesta;
        }
    }
}
